with Ada.IO_Exceptions;

with GNAT.IO;
use GNAT;

--
-- read a text file into a String
--


package body Text_File_Reader is

   function Read_Into_String( File_Name : in File_Name_Type )

         return Small_Output_String_Type
   is

      Resume_Flag : Boolean := false;

   begin

      return Read_Into_String( File_Name => File_Name,

                               Resume => Resume_Flag );

   end Read_Into_String;


   --
   -- read a text file into a String
   --

   function Read_Into_String( File_Name : in File_Name_Type;

                              Resume : in out Boolean )

         return Small_Output_String_Type
   is

      Not_EOF : Boolean;

   begin

      if( not Resume ) then

         Small_File_Contents_String_Type.Delete( Small_File_Contents,
               1,
               Small_File_Contents_String_Type.Length(Small_File_Contents));

         Text_IO.Open( File => Small_File_In,
                       Mode => Text_IO.In_File,
                       Name => File_Name );

      end if;

      while not Text_IO.End_Of_File( Small_File_In ) loop

         begin

            if( not Resume ) then

               --
               -- read in file, preserving existing /n or /r, or /n+/r or
               --
               --       other os-dependent linefeeds
               --

               Text_IO.Get_Immediate( File => Small_File_In,
                                      Item => Char_In,
                                      Available => Not_EOF );

            else

               Resume := false;

            end if;

            if( Not_EOF ) then

               Small_File_Contents_String_Type.Append(

                     Small_File_Contents,
                     Char_In );

            end if;

         end;

      end loop;

      Text_IO.Close( Small_File_In );

      if( Small_File_Contents_String_Type.Length(

            Small_File_Contents ) < 1 )
      then

         raise File_Empty;

      end if;


      return Small_File_Contents_String_Type.To_String( Small_File_Contents );


      exception

         when File_Empty =>

            IO.Put_Line( "File is empty or nothing read: " & File_Name );
            return "";

         when Text_IO.Name_Error =>

            IO.Put_Line( "File not found: " & File_Name );
            return "";

         when Text_IO.Status_Error =>

            IO.Put_Line( "File access unavailable: " & File_Name );
            return "";

         when Text_IO.Mode_Error =>

            IO.Put_Line( "File access unavailable: " & File_Name );
            return "";

         when IO_Exceptions.Use_Error =>

            IO.Put_Line( "File access unavailable: " & File_Name );
            return "";

         when Constraint_Error =>

         declare  -- Constraint_Error handling

            Please_Resume : Boolean := true;

         begin

            --
            -- replace offending character which is causing error upon
            --    Get_Immediate
            --

            Char_In := ' ';

            return Read_Into_String( File_Name, Resume => Please_Resume );

         end;  -- Constraint_Error handling

   end Read_Into_String;


   --
   -- read a text file into a String
   --
   --    output 'File_Contents' bounded string
   --

   procedure Read_Into_String( File_Name : in File_Name_Type )
   is

   begin

      Large_File_Contents_String_Type.Delete( Large_File_Contents,
            1,
            Large_File_Contents_String_Type.Length(Large_File_Contents));

      Large_File_IO.Open( File => Large_File_In,
                          Mode => Large_File_IO.In_File,
                          Name => File_Name );

      while not Large_File_IO.End_Of_File( Large_File_In ) loop

          begin

            --
            -- read in file w/o omission of /n or /r
            --

            Large_File_IO.Read( File => Large_File_In,
                                Item => Large_File_Buffer );

            Large_File_Contents_String_Type.Append(

                  Source => Large_File_Contents,

                  New_Item => Large_File_Buffer );

         end;

      end loop;

      Large_File_IO.Close( Large_File_In );

      if( Large_File_Contents_String_Type.Length(

            Large_File_Contents ) < 1 )
      then

         raise File_Empty;

      end if;


    exception

      when File_Empty =>

         IO.Put_Line( "File is empty or nothing read: " & File_Name );

      when Text_IO.Name_Error =>

         IO.Put_Line( "File not found: " & File_Name );

      when Text_IO.Status_Error =>

         IO.Put_Line( "File access unavailable: " & File_Name );

      when Text_IO.Mode_Error =>

         IO.Put_Line( "File access unavailable: " & File_Name );

      when IO_Exceptions.Use_Error =>

         IO.Put_Line( "File access unavailable: " & File_Name );

   end Read_Into_String;


end Text_File_Reader;